<?php

declare(strict_types=1);

namespace App\CustHub\Work;

use App\CustHub\Interfaces\OpenWorkApplicationInterface;
use App\CustHub\Mapper\ChCorpMapper;
use App\CustHub\Mapper\ChOpenWorkAgentMapper;
use App\CustHub\Mapper\ChOpenWorkAppMapper;
use App\CustHub\Model\ChCorp;
use App\Setting\Service\SettingConfigService;
use EasyWeChat\OpenWork\Message;
use FriendsOfHyperf\Lock\Exception\LockTimeoutException;
use Hyperf\Di\Annotation\Inject;
use Mine\Abstracts\AbstractService;
use function FriendsOfHyperf\Lock\lock;

class OpenWorkAgentService  extends AbstractService
{
    public $mapper;

    #[Inject]
    protected OpenWorkApplicationInterface $weWork;

    #[Inject]
    protected ChOpenWorkAppMapper $mcAppMapper;

    #[Inject]
    protected ChCorpMapper $corpMapper;

    public function __construct(ChOpenWorkAgentMapper $mapper)
    {
        $this->mapper = $mapper;
    }

    /**
     * 保存企业应用
     */
    public function saveWorkAgent(Message $message): bool
    {
        $suiteId = $message->SuiteId;
        $authCode = $message->AuthCode;
        $state = $message->State;
        if(!empty($state)){
            $stateArr = explode('A',$state);
            $authType = $stateArr[0] ?? 0;
            $mainUid = $stateArr[1] ?? 0;
        }else{
            $authType = 0;
            $mainUid = 0;
        }

        $app = $this->weWork->getOpenWork();
        $suiteAccessToken = $this->weWork->getSuiteAccessToken($app->getAccount()->getSuiteId(),$app->getAccount()->getSuiteSecret());
        $result = $this->weWork->getPermanentCode($suiteAccessToken->getToken(),$authCode);
        $openUserId = '';
        if(!empty($result['auth_user_info'])){
            $openUserId = $result['auth_user_info']['open_userid'];
        }

        $authCorpInfo = $result['auth_corp_info'];

        $corpName = $authCorpInfo['corp_name'];//企业名称
        $corpid = $authCorpInfo['corpid'];

        $agentList = $result['auth_info']['agent'];
        //新的单应用授权，永远只返回一个agent
        $agent = array_shift($agentList);

        $lock = lock( 'open_work_auth_lock:'.md5($corpid.$suiteId),4);
        try {
            $lock->block(2);
            $workAgentInfo = $this->mapper->getInfoByCorpidAndSuiteId($corpid,$suiteId);
            if(!empty($workAgentInfo)){
                $this->mapper->update($workAgentInfo['id'],[
                    'wx_secret' => $result['permanent_code']
                ]);
            }else{
                $accessToken = $this->weWork->getAccessToken($corpid, $result['permanent_code']);
                $agentInfo = $this->weWork->getAgentInfo($accessToken,$agent['agentid']);
                $authAppId = container()->get(SettingConfigService::class)->getConfigByKey('auth_app_id')['value'];
                $workAgentData = [
                    'app_id' => $authAppId,
                    'wx_corpid' => $corpid,
                    'corp_name' => $corpName,
                    'wx_suite_id' => $suiteId,
                    'wx_agent_id' => $agent['agentid'],
                    'wx_secret' => $result['permanent_code'],
                    'name' => $agent['name'],
                    'square_logo_url' => $agent['square_logo_url'],
                    'close' => $agentInfo['close'],
                    'description' => $agentInfo['description'],
                    'redirect_domain' => $agentInfo['redirect_domain'],
                    'report_location_flag' => $agentInfo['report_location_flag'],
                    'is_reportenter' => $agentInfo['isreportenter'],
                    'home_url' => $agentInfo['home_url'],
                    'auth_type' => $authType
                ];
                $this->save($workAgentData);
            }

            $corpInfo = ChCorp::query()
                ->where('main_uid', $mainUid)
                ->where('corp_name',$corpName)
                ->first();

            if(!empty($corpInfo)){
                //更新企业授权状态
                $this->corpMapper->model::query()
                    ->where('id',$corpInfo->id)
                    ->update([
                        'auth_corp_id' => $corpid,
                        'auth_status' => 1,
                        'auth_admin_id' => $openUserId
                    ]);
            }else{
                //新增授权企业
                $corpSaveData = [
                    'uid' => $mainUid,
                    'main_uid' => $mainUid,
                    'corp_name' => $corpName,
                    'corp_full_name' => $authCorpInfo['corp_full_name'] ?? '',
                    'corp_log' => $authCorpInfo['corp_square_logo_url'] ?? '',
                    'auth_corp_id' => $corpid,
                    'auth_status' => 1,
                    'auth_admin_id' => $openUserId
                ];
                $this->corpMapper->save($corpSaveData);
            }

            $this->mapper->delCache($authCorpInfo['corpid'],$suiteId);
            $this->corpMapper->clearAuthCache($corpid);
            return true;
        }catch (LockTimeoutException $e){
            return false;
        } finally {
            $lock->release();
        }
    }

    /**
     * 删除企业应用
     * @param string $suiteId
     * @param string $corpid
     * @return void
     * @throws \Exception
     */
    public function delWorkAgent(string $suiteId, string $corpid): void
    {
        $info = $this->mapper->model::query()
            ->where('wx_corpid',$corpid)
            ->where('wx_suite_id',$suiteId)
            ->first();

        if(!empty($info)){
            $this->mapper->delCache($corpid,$suiteId);
            $info->delete();

            $this->corpMapper->model::query()
                ->where('auth_corp_id',$corpid)
                ->update([
                    'auth_corp_id' => '',
                    'auth_status' => 0
                ]);
            $this->corpMapper->clearAuthCache($corpid);
        }
    }

    /**
     * 权限变更
     * @param Message $message
     * @return void
     * @throws \EasyWeChat\Kernel\Exceptions\HttpException
     * @throws \Psr\SimpleCache\InvalidArgumentException
     * @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface
     * @throws \Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface
     * @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface
     * @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface
     * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
     */
    public function changeAuth(Message $message): void
    {
        $AuthCorpId = $message->AuthCorpId;
        $suiteId = $message->SuiteId;

        $agentInfo = $this->mapper->getInfoByCorpidAndSuiteId($AuthCorpId,$suiteId);

        $app = $this->weWork->getOpenWork();
        $suiteAccessToken = $this->weWork->getSuiteAccessToken($app->getAccount()->getSuiteId(),$app->getAccount()->getSuiteSecret());
        $result = $this->weWork->getAuthInfo($suiteAccessToken->getToken(),$agentInfo['wx_corpid'],$agentInfo['wx_secret']);
        $auth_info = array_shift($result['auth_info']);
        $agent = array_shift($auth_info);
        $privilege = $agent['privilege'];
        if(!empty($privilege['allow_party']) || !empty($privilege['allow_user']) || !empty($privilege['allow_tag'])
            || !empty($privilege['extra_party']) || !empty($privilege['extra_user']) || !empty($privilege['extra_tag'])){
            $this->mapper->model::query()->where('id',$agentInfo['id'])->update(['status'=>1]);
        }
    }

    /**
     * @param string $corpWxid
     * @param int $authType 授权类型：0=平台
     * @return bool
     */
    public function checkAuthStatus(string $corpWxid,int $authType): bool
    {
        return $this->mapper->model::query()
            ->where('wx_corpid',$corpWxid)
            ->where('auth_type',$authType)
            ->exists();
    }
}